home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / program / tcpdumpb.zip / libpcap / bpf_filter.c next >
C/C++ Source or Header  |  1996-06-23  |  11KB  |  535 lines

  1. /*-
  2.  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * This code is derived from the Stanford/CMU enet packet filter,
  6.  * (net/enet.c) distributed as part of 4.3BSD, and code contributed
  7.  * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence 
  8.  * Berkeley Laboratory.
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions
  12.  * are met:
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  * 3. All advertising materials mentioning features or use of this software
  19.  *    must display the following acknowledgement:
  20.  *    This product includes software developed by the University of
  21.  *    California, Berkeley and its contributors.
  22.  * 4. Neither the name of the University nor the names of its contributors
  23.  *    may be used to endorse or promote products derived from this software
  24.  *    without specific prior written permission.
  25.  *
  26.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  27.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  30.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  35.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  36.  * SUCH DAMAGE.
  37.  *
  38.  *    @(#)bpf.c    7.5 (Berkeley) 7/15/91
  39.  *
  40.  * static char rcsid[] =
  41.  * "$Header: bpf_filter.c,v 1.29 96/06/23 13:44:02 leres Exp $";
  42.  */
  43. #if !(defined(lint) || defined(KERNEL))
  44. static char rcsid[] =
  45.     "@(#) $Header: bpf_filter.c,v 1.29 96/06/23 13:44:02 leres Exp $ (LBL)";
  46. #endif
  47.  
  48. #include <sys/param.h>
  49. #include <sys/types.h>
  50. #include <sys/time.h>
  51. #include <net/bpf.h>
  52.  
  53. #ifndef KERNEL
  54. #include <stdlib.h>
  55. #endif
  56.  
  57. #define int32 bpf_int32
  58. #define u_int32 bpf_u_int32
  59.  
  60. #ifndef LBL_ALIGN
  61. #if defined(sparc) || defined(mips) || defined(ibm032) || \
  62.     defined(__alpha) || defined(__hpux)
  63. #define LBL_ALIGN
  64. #endif
  65. #endif
  66.  
  67. #ifndef LBL_ALIGN
  68. #include <netinet/in.h>
  69.  
  70. #define EXTRACT_SHORT(p)    ((u_short)ntohs(*(u_short *)p))
  71. #define EXTRACT_LONG(p)        (ntohl(*(u_int32 *)p))
  72. #else
  73. #define EXTRACT_SHORT(p)\
  74.     ((u_short)\
  75.         ((u_short)*((u_char *)p+0)<<8|\
  76.          (u_short)*((u_char *)p+1)<<0))
  77. #define EXTRACT_LONG(p)\
  78.         ((u_int32)*((u_char *)p+0)<<24|\
  79.          (u_int32)*((u_char *)p+1)<<16|\
  80.          (u_int32)*((u_char *)p+2)<<8|\
  81.          (u_int32)*((u_char *)p+3)<<0)
  82. #endif
  83.  
  84. #ifdef KERNEL
  85. #include <sys/mbuf.h>
  86. #define MINDEX(len, m, k) \
  87. { \
  88.     len = m->m_len; \
  89.     while (k >= len) { \
  90.         k -= len; \
  91.         m = m->m_next; \
  92.         if (m == 0) \
  93.             return 0; \
  94.         len = m->m_len; \
  95.     } \
  96. }
  97.  
  98. static int
  99. m_xword(m, k, err)
  100.     register struct mbuf *m;
  101.     register int k, *err;
  102. {
  103.     register int len;
  104.     register u_char *cp, *np;
  105.     register struct mbuf *m0;
  106.  
  107.     MINDEX(len, m, k);
  108.     cp = mtod(m, u_char *) + k;
  109.     if (len - k >= 4) {
  110.         *err = 0;
  111.         return EXTRACT_LONG(cp);
  112.     }
  113.     m0 = m->m_next;
  114.     if (m0 == 0 || m0->m_len + len - k < 4)
  115.         goto bad;
  116.     *err = 0;
  117.     np = mtod(m0, u_char *);
  118.     switch (len - k) {
  119.  
  120.     case 1:
  121.         return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
  122.  
  123.     case 2:
  124.         return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1];
  125.  
  126.     default:
  127.         return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0];
  128.     }
  129.     bad:
  130.     *err = 1;
  131.     return 0;
  132. }
  133.  
  134. static int
  135. m_xhalf(m, k, err)
  136.     register struct mbuf *m;
  137.     register int k, *err;
  138. {
  139.     register int len;
  140.     register u_char *cp;
  141.     register struct mbuf *m0;
  142.  
  143.     MINDEX(len, m, k);
  144.     cp = mtod(m, u_char *) + k;
  145.     if (len - k >= 2) {
  146.         *err = 0;
  147.         return EXTRACT_SHORT(cp);
  148.     }
  149.     m0 = m->m_next;
  150.     if (m0 == 0)
  151.         goto bad;
  152.     *err = 0;
  153.     return (cp[0] << 8) | mtod(m0, u_char *)[0];
  154.  bad:
  155.     *err = 1;
  156.     return 0;
  157. }
  158. #endif
  159.  
  160. /*
  161.  * Execute the filter program starting at pc on the packet p
  162.  * wirelen is the length of the original packet
  163.  * buflen is the amount of data present
  164.  */
  165. u_int
  166. bpf_filter(pc, p, wirelen, buflen)
  167.     register struct bpf_insn *pc;
  168.     register u_char *p;
  169.     u_int wirelen;
  170.     register u_int buflen;
  171. {
  172.     register u_int32 A, X;
  173.     register int k;
  174.     int32 mem[BPF_MEMWORDS];
  175.  
  176.     if (pc == 0)
  177.         /*
  178.          * No filter means accept all.
  179.          */
  180.         return (u_int)-1;
  181.     A = 0;
  182.     X = 0;
  183.     --pc;
  184.     while (1) {
  185.         ++pc;
  186.         switch (pc->code) {
  187.  
  188.         default:
  189. #ifdef KERNEL
  190.             return 0;
  191. #else
  192.             abort();
  193. #endif            
  194.         case BPF_RET|BPF_K:
  195.             return (u_int)pc->k;
  196.  
  197.         case BPF_RET|BPF_A:
  198.             return (u_int)A;
  199.  
  200.         case BPF_LD|BPF_W|BPF_ABS:
  201.             k = pc->k;
  202.             if (k + sizeof(int32) > buflen) {
  203. #ifdef KERNEL
  204.                 int merr;
  205.  
  206.                 if (buflen != 0)
  207.                     return 0;
  208.                 A = m_xword((struct mbuf *)p, k, &merr);
  209.                 if (merr != 0)
  210.                     return 0;
  211.                 continue;
  212. #else
  213.                 return 0;
  214. #endif
  215.             }
  216.             A = EXTRACT_LONG(&p[k]);
  217.             continue;
  218.  
  219.         case BPF_LD|BPF_H|BPF_ABS:
  220.             k = pc->k;
  221.             if (k + sizeof(short) > buflen) {
  222. #ifdef KERNEL
  223.                 int merr;
  224.  
  225.                 if (buflen != 0)
  226.                     return 0;
  227.                 A = m_xhalf((struct mbuf *)p, k, &merr);
  228.                 continue;
  229. #else
  230.                 return 0;
  231. #endif
  232.             }
  233.             A = EXTRACT_SHORT(&p[k]);
  234.             continue;
  235.  
  236.         case BPF_LD|BPF_B|BPF_ABS:
  237.             k = pc->k;
  238.             if (k >= buflen) {
  239. #ifdef KERNEL
  240.                 register struct mbuf *m;
  241.                 register int len;
  242.  
  243.                 if (buflen != 0)
  244.                     return 0;
  245.                 m = (struct mbuf *)p;
  246.                 MINDEX(len, m, k);
  247.                 A = mtod(m, u_char *)[k];
  248.                 continue;
  249. #else
  250.                 return 0;
  251. #endif
  252.             }
  253.             A = p[k];
  254.             continue;
  255.  
  256.         case BPF_LD|BPF_W|BPF_LEN:
  257.             A = wirelen;
  258.             continue;
  259.  
  260.         case BPF_LDX|BPF_W|BPF_LEN:
  261.             X = wirelen;
  262.             continue;
  263.  
  264.         case BPF_LD|BPF_W|BPF_IND:
  265.             k = X + pc->k;
  266.             if (k + sizeof(int32) > buflen) {
  267. #ifdef KERNEL
  268.                 int merr;
  269.  
  270.                 if (buflen != 0)
  271.                     return 0;
  272.                 A = m_xword((struct mbuf *)p, k, &merr);
  273.                 if (merr != 0)
  274.                     return 0;
  275.                 continue;
  276. #else
  277.                 return 0;
  278. #endif
  279.             }
  280.             A = EXTRACT_LONG(&p[k]);
  281.             continue;
  282.  
  283.         case BPF_LD|BPF_H|BPF_IND:
  284.             k = X + pc->k;
  285.             if (k + sizeof(short) > buflen) {
  286. #ifdef KERNEL
  287.                 int merr;
  288.  
  289.                 if (buflen != 0)
  290.                     return 0;
  291.                 A = m_xhalf((struct mbuf *)p, k, &merr);
  292.                 if (merr != 0)
  293.                     return 0;
  294.                 continue;
  295. #else
  296.                 return 0;
  297. #endif
  298.             }
  299.             A = EXTRACT_SHORT(&p[k]);
  300.             continue;
  301.  
  302.         case BPF_LD|BPF_B|BPF_IND:
  303.             k = X + pc->k;
  304.             if (k >= buflen) {
  305. #ifdef KERNEL
  306.                 register struct mbuf *m;
  307.                 register int len;
  308.  
  309.                 if (buflen != 0)
  310.                     return 0;
  311.                 m = (struct mbuf *)p;
  312.                 MINDEX(len, m, k);
  313.                 A = mtod(m, u_char *)[k];
  314.                 continue;
  315. #else
  316.                 return 0;
  317. #endif
  318.             }
  319.             A = p[k];
  320.             continue;
  321.  
  322.         case BPF_LDX|BPF_MSH|BPF_B:
  323.             k = pc->k;
  324.             if (k >= buflen) {
  325. #ifdef KERNEL
  326.                 register struct mbuf *m;
  327.                 register int len;
  328.  
  329.                 if (buflen != 0)
  330.                     return 0;
  331.                 m = (struct mbuf *)p;
  332.                 MINDEX(len, m, k);
  333.                 X = (mtod(m, char *)[k] & 0xf) << 2;
  334.                 continue;
  335. #else
  336.                 return 0;
  337. #endif
  338.             }
  339.             X = (p[pc->k] & 0xf) << 2;
  340.             continue;
  341.  
  342.         case BPF_LD|BPF_IMM:
  343.             A = pc->k;
  344.             continue;
  345.  
  346.         case BPF_LDX|BPF_IMM:
  347.             X = pc->k;
  348.             continue;
  349.  
  350.         case BPF_LD|BPF_MEM:
  351.             A = mem[pc->k];
  352.             continue;
  353.             
  354.         case BPF_LDX|BPF_MEM:
  355.             X = mem[pc->k];
  356.             continue;
  357.  
  358.         case BPF_ST:
  359.             mem[pc->k] = A;
  360.             continue;
  361.  
  362.         case BPF_STX:
  363.             mem[pc->k] = X;
  364.             continue;
  365.  
  366.         case BPF_JMP|BPF_JA:
  367.             pc += pc->k;
  368.             continue;
  369.  
  370.         case BPF_JMP|BPF_JGT|BPF_K:
  371.             pc += (A > pc->k) ? pc->jt : pc->jf;
  372.             continue;
  373.  
  374.         case BPF_JMP|BPF_JGE|BPF_K:
  375.             pc += (A >= pc->k) ? pc->jt : pc->jf;
  376.             continue;
  377.  
  378.         case BPF_JMP|BPF_JEQ|BPF_K:
  379.             pc += (A == pc->k) ? pc->jt : pc->jf;
  380.             continue;
  381.  
  382.         case BPF_JMP|BPF_JSET|BPF_K:
  383.             pc += (A & pc->k) ? pc->jt : pc->jf;
  384.             continue;
  385.  
  386.         case BPF_JMP|BPF_JGT|BPF_X:
  387.             pc += (A > X) ? pc->jt : pc->jf;
  388.             continue;
  389.  
  390.         case BPF_JMP|BPF_JGE|BPF_X:
  391.             pc += (A >= X) ? pc->jt : pc->jf;
  392.             continue;
  393.  
  394.         case BPF_JMP|BPF_JEQ|BPF_X:
  395.             pc += (A == X) ? pc->jt : pc->jf;
  396.             continue;
  397.  
  398.         case BPF_JMP|BPF_JSET|BPF_X:
  399.             pc += (A & X) ? pc->jt : pc->jf;
  400.             continue;
  401.  
  402.         case BPF_ALU|BPF_ADD|BPF_X:
  403.             A += X;
  404.             continue;
  405.             
  406.         case BPF_ALU|BPF_SUB|BPF_X:
  407.             A -= X;
  408.             continue;
  409.             
  410.         case BPF_ALU|BPF_MUL|BPF_X:
  411.             A *= X;
  412.             continue;
  413.             
  414.         case BPF_ALU|BPF_DIV|BPF_X:
  415.             if (X == 0)
  416.                 return 0;
  417.             A /= X;
  418.             continue;
  419.             
  420.         case BPF_ALU|BPF_AND|BPF_X:
  421.             A &= X;
  422.             continue;
  423.             
  424.         case BPF_ALU|BPF_OR|BPF_X:
  425.             A |= X;
  426.             continue;
  427.  
  428.         case BPF_ALU|BPF_LSH|BPF_X:
  429.             A <<= X;
  430.             continue;
  431.  
  432.         case BPF_ALU|BPF_RSH|BPF_X:
  433.             A >>= X;
  434.             continue;
  435.  
  436.         case BPF_ALU|BPF_ADD|BPF_K:
  437.             A += pc->k;
  438.             continue;
  439.             
  440.         case BPF_ALU|BPF_SUB|BPF_K:
  441.             A -= pc->k;
  442.             continue;
  443.             
  444.         case BPF_ALU|BPF_MUL|BPF_K:
  445.             A *= pc->k;
  446.             continue;
  447.             
  448.         case BPF_ALU|BPF_DIV|BPF_K:
  449.             A /= pc->k;
  450.             continue;
  451.             
  452.         case BPF_ALU|BPF_AND|BPF_K:
  453.             A &= pc->k;
  454.             continue;
  455.             
  456.         case BPF_ALU|BPF_OR|BPF_K:
  457.             A |= pc->k;
  458.             continue;
  459.  
  460.         case BPF_ALU|BPF_LSH|BPF_K:
  461.             A <<= pc->k;
  462.             continue;
  463.  
  464.         case BPF_ALU|BPF_RSH|BPF_K:
  465.             A >>= pc->k;
  466.             continue;
  467.  
  468.         case BPF_ALU|BPF_NEG:
  469.             A = -A;
  470.             continue;
  471.  
  472.         case BPF_MISC|BPF_TAX:
  473.             X = A;
  474.             continue;
  475.  
  476.         case BPF_MISC|BPF_TXA:
  477.             A = X;
  478.             continue;
  479.         }
  480.     }
  481. }
  482.  
  483. #ifdef KERNEL
  484. /*
  485.  * Return true if the 'fcode' is a valid filter program.
  486.  * The constraints are that each jump be forward and to a valid
  487.  * code.  The code must terminate with either an accept or reject. 
  488.  * 'valid' is an array for use by the routine (it must be at least
  489.  * 'len' bytes long).  
  490.  *
  491.  * The kernel needs to be able to verify an application's filter code.
  492.  * Otherwise, a bogus program could easily crash the system.
  493.  */
  494. int
  495. bpf_validate(f, len)
  496.     struct bpf_insn *f;
  497.     int len;
  498. {
  499.     register int i;
  500.     register struct bpf_insn *p;
  501.  
  502.     for (i = 0; i < len; ++i) {
  503.         /*
  504.          * Check that that jumps are forward, and within 
  505.          * the code block.
  506.          */
  507.         p = &f[i];
  508.         if (BPF_CLASS(p->code) == BPF_JMP) {
  509.             register int from = i + 1;
  510.  
  511.             if (BPF_OP(p->code) == BPF_JA) {
  512.                 if (from + p->k >= len)
  513.                     return 0;
  514.             }
  515.             else if (from + p->jt >= len || from + p->jf >= len)
  516.                 return 0;
  517.         }
  518.         /*
  519.          * Check that memory operations use valid addresses.
  520.          */
  521.         if ((BPF_CLASS(p->code) == BPF_ST ||
  522.              (BPF_CLASS(p->code) == BPF_LD && 
  523.               (p->code & 0xe0) == BPF_MEM)) &&
  524.             (p->k >= BPF_MEMWORDS || p->k < 0))
  525.             return 0;
  526.         /*
  527.          * Check for constant division by 0.
  528.          */
  529.         if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
  530.             return 0;
  531.     }
  532.     return BPF_CLASS(f[len - 1].code) == BPF_RET;
  533. }
  534. #endif
  535.